/**    
 * 文件名：ApprovalService.java</br>
 *    
 * 版本信息：v1.0</br>
 * 日期：2017年10月10日</br>
 * © 2005-2017 雷技信息科技（上海）有限公司版权所有</br>
 *
 */
package com.logic.landseaserver.models.approval.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.logic.common.security.SecurityUtils;
import com.logic.landseaserver.common.LandeaConstants.ApprovalStatus;
import com.logic.landseaserver.common.LandeaConstants.RoleCode;
import com.logic.landseaserver.common.exception.LandseaException;
import com.logic.landseaserver.common.exception.ResultCodes.ApprovalResultCode;
import com.logic.landseaserver.domain.ApprovalLogRecord;
import com.logic.landseaserver.domain.ApprovalRecord;
import com.logic.landseaserver.domain.ApprovalRoleFlowRecord;
import com.logic.landseaserver.domain.ApprovalTempRecord;
import com.logic.landseaserver.models.approval.bean.ApprovalCheckResult;
import com.logic.landseaserver.models.approval.bean.ApprovalLogReq;
import com.logic.landseaserver.models.approval.bean.ApprovalReq;
import com.logic.landseaserver.models.approval.bean.GetApprovalFlowResp;
import com.logic.landseaserver.models.approval.bean.SubmitApprovalReq;
import com.logic.landseaserver.models.approval.taskhandle.AbractApprovalHandler;
import com.logic.landseaserver.persistence.read.ApprovalLogRecordReadMapper;
import com.logic.landseaserver.persistence.read.ApprovalRecordReadMapper;
import com.logic.landseaserver.persistence.read.ApprovalRoleFlowRecordReadMapper;
import com.logic.landseaserver.persistence.read.ApprovalTempRecordReadMapper;
import com.logic.landseaserver.persistence.write.ApprovalLogRecordWriteMapper;
import com.logic.landseaserver.persistence.write.ApprovalRecordWriteMapper;
import com.logic.system.AppContext;
import com.logic.system.persistence.read.UserReadMapper;
import com.logic.system.ws.dto.UserRoleDTO;

/**
 *
 * 项目名称：system-server</br>
 * 类名称：ApprovalService</br>
 * 类描述：</br>
 * 创建人：Aaron</br>
 * 创建时间：2017年10月10日 下午5:00:05</br>
 * 
 * @version 1.0
 *
 */
@Service
public class ApprovalService
{
    private static final Logger LOGGER = LoggerFactory.getLogger(ApprovalService.class);
    
    @Autowired
    private UserReadMapper userReadMapper;
    
    @Autowired
    private ApprovalRoleFlowRecordReadMapper approvalRoleFlowRecordReadMapper;
    
    @Autowired
    private ApprovalTempRecordReadMapper approvalTempRecordReadMapper;
    
    @Autowired
    private ApprovalRecordWriteMapper approvalRecordWriteMapper;
    
    @Autowired
    private ApprovalRecordReadMapper approvalRecordReadMapper;
    
    @Autowired
    private ApprovalLogRecordReadMapper approvalLogRecordReadMapper;
    
    @Autowired
    private AppContext appContext;
    
    @Autowired
    private ApprovalLogRecordWriteMapper approvalLogRecordWriteMapper;
    
    /**
     * 
     * [简要描述]：根据当前操作人及场景获取可选流程列表</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-10-11)</br>
     * 
     * @throws LandseaException
     *
     *
     */
    public GetApprovalFlowResp getApprovalFlow(String taskType)
        throws LandseaException
    {
        try
        {
            GetApprovalFlowResp result = new GetApprovalFlowResp();
            
            // 获取当前登录者
            Integer userId = SecurityUtils.getCurrentLogin().getUserId();
            
            // 获取登陆者权限最大的角色
            List<UserRoleDTO> roleList = userReadMapper.getUserRolesWithCodeByUserId(userId);
            if (CollectionUtils.isEmpty(roleList))
            {
                return result;
            }
            
            // 根据taskType获取所有的审批流程
            List<ApprovalRoleFlowRecord> roleFlowList = approvalRoleFlowRecordReadMapper.getListByTaskType(taskType);
            if (CollectionUtils.isEmpty(roleFlowList))
            {
                return result;
            }
            
            // 处理成Map
            Map<String, ApprovalRoleFlowRecord> roleFlowMap = new HashMap<String, ApprovalRoleFlowRecord>();
            for (ApprovalRoleFlowRecord record : roleFlowList)
            {
                roleFlowMap.put(record.getApproveRoleCode(), record);
            }
            
            // 检查总部运营负责人
            String destRoleCode = checkRoleFlow(RoleCode.ZBYYFZR, roleFlowMap, roleList);
            if (StringUtils.isNotEmpty(destRoleCode))
            {
                // 封装结果
                buildResult(result, destRoleCode, roleFlowMap.get(destRoleCode));
                return result;
            }
            // 检查区域经理
            destRoleCode = checkRoleFlow(RoleCode.QYYYJL, roleFlowMap, roleList);
            if (StringUtils.isNotEmpty(destRoleCode))
            {
                // 封装结果
                buildResult(result, destRoleCode, roleFlowMap.get(destRoleCode));
                return result;
            }
            // 检查店长
            destRoleCode = checkRoleFlow(RoleCode.DZ, roleFlowMap, roleList);
            if (StringUtils.isNotEmpty(destRoleCode))
            {
                // 封装结果
                buildResult(result, destRoleCode, roleFlowMap.get(destRoleCode));
                return result;
            }
            // 检查管家
            destRoleCode = checkRoleFlow(RoleCode.GJ, roleFlowMap, roleList);
            if (StringUtils.isNotEmpty(destRoleCode))
            {
                // 封装结果
                buildResult(result, destRoleCode, roleFlowMap.get(destRoleCode));
                return result;
            }
            
            return result;
        }
        catch (Exception e)
        {
            LOGGER.error("getApprovalFlow|获取审核流程失败.taskType=" + taskType, e);
            throw LandseaException.createException(ApprovalResultCode.E00650001, e);
        }
    }
    
    // 检查角色是否存在流程
    private String checkRoleFlow(String checkRoleCode, Map<String, ApprovalRoleFlowRecord> roleFlowMap,
        List<UserRoleDTO> roleList)
    {
        String resultCode = null;
        
        // 循环用户所有角色code，从大到小
        for (UserRoleDTO userRole : roleList)
        {
            String roleCode = userRole.getCode();
            
            // 检查总部运营负责人
            if (checkRoleCode.equals(roleCode))
            {
                // 检查是否有对应流程
                if (roleFlowMap.containsKey(roleCode))
                {
                    resultCode = roleCode;
                    break;
                }
            }
        }
        return resultCode;
    }
    
    /**
     * 
     * [简要描述]：提交审核</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-10-12)</br>
     *
     * @param submitApprovalReq
     * @throws LandseaException
     *
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {LandseaException.class, Exception.class})
    public void submitApproval(SubmitApprovalReq submitApprovalReq)
        throws LandseaException
    {
        try
        {
            LOGGER.info("submitApproval|提交审核｜" + submitApprovalReq.toString());
            
            // 获取处理bean
            String taskType = submitApprovalReq.getTaskType();
            String beanId = taskType + AbractApprovalHandler.BEANID;
            Object handerObject = appContext.getBean(beanId);
            if (null == handerObject)
            {
                LOGGER.error("submitApproval|taskType非法,taskType=" + taskType);
                throw LandseaException.createException(ApprovalResultCode.E00640001);
            }
            AbractApprovalHandler handler = (AbractApprovalHandler)handerObject;
            
            // 检查
            ApprovalCheckResult checkResult = handler.submitCheck(submitApprovalReq);
            
            // 获取审核状态及节点,提交审核，审核节点获取最小的
            ApprovalTempRecord currentApprovalRecord = getCurrentNode(checkResult.getFlowTempList());
            checkResult.setNextApprovalTempRecord(currentApprovalRecord);
            
            Integer approvalId = null;
            String approvalStatus = currentApprovalRecord.getApproveStatus();
            int nodeId = currentApprovalRecord.getNodeId();
            
            // 给自定义的用的
            ApprovalRecord customApprovalRecord = new ApprovalRecord();
            
            ApprovalRecord approvalRecord = checkResult.getCurrentApprovalRecord();
            // 如果是审批拒绝之后提交的，要走更新
            if (null != approvalRecord && ApprovalStatus.AREFUSED.equals(approvalRecord.getApproveStatus()))
            {
                approvalId = approvalRecord.getId();
                ApprovalRecord updateApproval = new ApprovalRecord();
                updateApproval.setId(approvalId);
                updateApproval.setFlowTempId(submitApprovalReq.getFlowTempId());
                updateApproval.setNodeId(nodeId);
                updateApproval.setApproveStatus(approvalStatus);
                updateApproval.setLastModifiedBy(SecurityUtils.getCurrentLogin().getUserId());
                updateApproval.setLastModifiedDtm(new Date());
                approvalRecordWriteMapper.updateByPrimaryKeySelective(updateApproval);
                
                customApprovalRecord = updateApproval;
            }
            else
            {
                // 入库审核表
                ApprovalRecord insertApproval = new ApprovalRecord();
                insertApproval.setTaskId(submitApprovalReq.getTaskId());
                insertApproval.setApproveStatus(approvalStatus);
                insertApproval.setTaskType(submitApprovalReq.getTaskType());
                insertApproval.setFlowTempId(submitApprovalReq.getFlowTempId());
                insertApproval.setNodeId(nodeId);
                insertApproval.initCommonField();
                approvalRecordWriteMapper.insertSelective(insertApproval);
                approvalId = insertApproval.getId();
                
                customApprovalRecord = insertApproval;
            }
            
            // 入库日志
            Integer userId = SecurityUtils.getCurrentLogin().getUserId();
            List<UserRoleDTO> roleList = userReadMapper.getUserRolesWithCodeByUserId(userId);
            
            // 当前操作人有多个角色，随便取一个
            String currentRoleCode = null;
            if (CollectionUtils.isNotEmpty(roleList))
            {
                currentRoleCode = roleList.get(0).getCode();
            }
            // 获取审核用户的名称
            String username = approvalRecordReadMapper.selectApprovalUserName(userId);
            ApprovalLogRecord insertLog = new ApprovalLogRecord();
            insertLog.initCommonField();
            insertLog.setApprovalId(approvalId);
            // 提交审批，此处空着
            insertLog.setApprovalStatus(null);
            insertLog.setComment("提交审批");
            insertLog.setUserId(userId);
            insertLog.setUsername(username);
            insertLog.setApprovalRoleCode(currentRoleCode);
            insertLog.setApprovalTime(new Date());
            approvalLogRecordWriteMapper.insertSelective(insertLog);
            
            // 处理自定义
            customApprovalRecord.setTaskId(submitApprovalReq.getTaskId());
            customApprovalRecord.setTaskType(taskType);
            handler.submitCustom(customApprovalRecord, checkResult);
        }
        catch (
        
        LandseaException e)
        {
            throw e;
        }
        catch (
        
        Exception e)
        {
            LOGGER.error("submitApproval error.", e);
            throw LandseaException.createException(ApprovalResultCode.E00650004, e);
        }
    }
    
    /**
     * 
     * [简要描述]：组装节点</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-10-12)</br>
     *
     * @param resp
     * @param roleCode
     * @param approvalRoleFlowRecord
     *
     */
    private void buildResult(GetApprovalFlowResp resp, String roleCode, ApprovalRoleFlowRecord approvalRoleFlowRecord)
    {
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
        resp.setResultList(resultList);
        
        String flowIds = approvalRoleFlowRecord.getFlowTempIds();
        if (StringUtils.isEmpty(flowIds))
        {
            return;
        }
        String[] flowTempIdArr = flowIds.split(",");
        Map<String, Object> flowMap = null;
        for (String flowTempId : flowTempIdArr)
        {
            // 查询审核流程模板表
            List<ApprovalTempRecord> templist = approvalTempRecordReadMapper.selectByFlowTempId(flowTempId);
            if (CollectionUtils.isEmpty(templist))
            {
                continue;
            }
            flowMap = new HashMap<String, Object>();
            List<String> nodeList = new ArrayList<String>();
            for (ApprovalTempRecord tempRecord : templist)
            {
                nodeList.add(tempRecord.getNodeName());
            }
            flowMap.put("flowTempId", flowTempId);
            flowMap.put("nodeList", nodeList);
            
            resultList.add(flowMap);
        }
    }
    
    /**
     * 
     * [简要描述]：获取第一个审核节点</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-10-13)</br>
     *
     * @param list
     * @return
     *
     */
    private ApprovalTempRecord getCurrentNode(List<ApprovalTempRecord> list)
    {
        Collections.sort(list, new Comparator<ApprovalTempRecord>()
        {
            @Override
            public int compare(ApprovalTempRecord o1, ApprovalTempRecord o2)
            {
                if (o1.getNodeId().intValue() >= o2.getNodeId().intValue())
                {
                    return 1;
                }
                
                return -1;
            }
        });
        
        return list.get(0);
    }
    
    /**
     * 
     * [简要描述]：审核</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-10-13)</br>
     *
     * @param approvalReq
     * @throws LandseaException
     *
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {LandseaException.class, Exception.class})
    public void approval(ApprovalReq approvalReq)
        throws LandseaException
    {
        LOGGER.info("approval|审核|" + approvalReq.toString());
        
        // 获取处理bean
        String taskType = approvalReq.getTaskType();
        String beanId = taskType + AbractApprovalHandler.BEANID;
        Object handerObject = appContext.getBean(beanId);
        if (null == handerObject)
        {
            LOGGER.error("approval|taskType非法,taskType=" + taskType);
            throw LandseaException.createException(ApprovalResultCode.E00640001);
        }
        AbractApprovalHandler handler = (AbractApprovalHandler)handerObject;
        
        handler.approval(approvalReq);
        
        LOGGER.info("approval|审核操作完成|" + approvalReq.toString());
    }
    
    /**
     * 
     * [简要描述]：查询审核日志</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-10-16)</br>
     *
     * @param approvalLogReq
     * @throws LandseaException
     *
     */
    public List<ApprovalLogRecord> queryApprovalLog(ApprovalLogReq approvalLogReq)
        throws LandseaException
    {
        List<ApprovalLogRecord> resultList = new ArrayList<ApprovalLogRecord>();
        
        try
        {
            // 查询审核ID
            // 获取审核
            ApprovalRecord queryCondition = new ApprovalRecord();
            queryCondition.setTaskId(approvalLogReq.getTaskId());
            queryCondition.setTaskType(approvalLogReq.getTaskType());
            ApprovalRecord approvalRecord = approvalRecordReadMapper.selectByTask(queryCondition);
            if (null == approvalRecord || approvalRecord.getDeleted())
            {
                return resultList;
            }
            
            resultList = approvalLogRecordReadMapper.queryApprovalLog(approvalRecord.getId());
            
            return resultList;
        }
        catch (Exception e)
        {
            LOGGER.error("queryApprovalLog error." + approvalLogReq.toString());
            throw LandseaException.createException(ApprovalResultCode.E00650011);
        }
    }
}
